﻿/**
Провайдер AnyBalance (http://any-balance-providers.googlecode.com)
*/

var g_headers = {
	'Content-Type':'application/x-www-form-urlencoded',
	'Accept':'*/*',
	'Accept-Language':'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
	'Connection':'keep-alive',
	'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36',
	'X-Requested-With':'XMLHttpRequest',
	'Origin':'https://www.personal-account.kiev.ua'
};

function main(){
    var prefs = AnyBalance.getPreferences();
    var baseurl = 'https://www.personal-account.kiev.ua/';
    AnyBalance.setDefaultCharset('utf-8'); 
	//Пароль в SHA-1
	var pass = sha1Hash(prefs.password);
	
	var html = AnyBalance.requestGet(baseurl + 'entrance/', g_headers);
	
	var data = {
		'login':prefs.login,
		'password':pass
	};
	
    html = AnyBalance.requestPost(baseurl + 'entrance/submit/', {
		'data':JSON.stringify(data)
	}, addHeaders({Referer: baseurl + 'entrance/'})); 
	
	var json = getJson(html);
    if(!json.result){
        if(json.reason)
            throw new AnyBalance.Error(json.reason);
        throw new AnyBalance.Error('Не удалось зайти в личный кабинет. Сайт изменен?');
    }
	html = AnyBalance.requestGet(baseurl + 'dashboard/', g_headers);
	
	var subrscrArr = sumParam(html, null, null, /subscr_(\d+)/ig);
	AnyBalance.trace('Найдено счетов: ' + subrscrArr.length);
	
	for(var i =0; i < subrscrArr.length; i++) {
		var subrscr = subrscrArr[i];
		html = AnyBalance.requestGet(baseurl + 'dashboard/lastbills/' + subrscr, g_headers);
		// Если не указан счет, берем первый и уходим.
		if(!prefs.num) {
			AnyBalance.trace('Не указан счет по которому надо получать данные, берем первый');
			break;
		}
		var account = getParam(html, null, null, /([^>]*>){14}/i, replaceTagsAndSpaces, html_entity_decode);
		AnyBalance.trace('Счет: ' + account);
		if(account != prefs.num)
			AnyBalance.trace('Счет: ' + account + ' не соответствует заданному в настройках: ' + prefs.num);
		else
			break;
	}

	var bills = sumParam(html, null, null, /<tr>\s*([^]*?)\s*<\/tr>/ig);
	if(!bills.length)
		throw new AnyBalance.Error('Не найден ни один счет.');

	var result = {success: true};

	for(var i = 0, toi = bills.length, bill, billhref, summ; i < toi; i++){
		billhref = getParam(bills[i], null, null, /href="\/([^"]+)/i);
		bill = AnyBalance.requestGet(baseurl + billhref, g_headers);

		getParam(bills[i], result, 'type' + i, /Показати деталі даного рахунку[^>]*>([^<]+)/i, replaceTagsAndSpaces, html_entity_decode);
		sumParam(bill, result, 'value' + i, /_AccruedSumm[^]*?value="([^"]+)/ig, replaceTagsAndSpaces, parseBalance, aggregate_sum);
	}
	
    AnyBalance.setResult(result);
}

// Безопасность? не, не слышали :)
function sha1Hash(msg)
{
	
		//
		// function 'f' [�4.1.1]
		//
		function f(s, x, y, z) 
		{
				switch (s) {
				case 0: return (x & y) ^ (~x & z);           // Ch()
				case 1: return x ^ y ^ z;                    // Parity()
				case 2: return (x & y) ^ (x & z) ^ (y & z);  // Maj()
				case 3: return x ^ y ^ z;                    // Parity()
				}
		}
		 
		//
		// rotate left (circular left shift) value x by n positions [�3.2.5]
		//
		function ROTL(x, n)
		{
				return (x<<n) | (x>>>(32-n));
		}
	
    // constants [�4.2.1]
    var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
 
 
    // PREPROCESSING 
 
    msg += String.fromCharCode(0x80); // add trailing '1' bit to string [�5.1.1]
 
    // convert string msg into 512-bit/16-integer blocks arrays of ints [�5.2.1]
    var l = Math.ceil(msg.length/4) + 2;  // long enough to contain msg plus 2-word length
    var N = Math.ceil(l/16);              // in N 16-int blocks
    var M = new Array(N);
    for (var i=0; i<N; i++) {
        M[i] = new Array(16);
        for (var j=0; j<16; j++) {  // encode 4 chars per integer, big-endian encoding
            M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) | 
                      (msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
        }
    }
    // add length (in bits) into final pair of 32-bit integers (big-endian) [5.1.1]
    // note: most significant word would be ((len-1)*8 >>> 32, but since JS converts
    // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators
    M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14])
    M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;
 
    // set initial hash value [�5.3.1]
    var H0 = 0x67452301;
    var H1 = 0xefcdab89;
    var H2 = 0x98badcfe;
    var H3 = 0x10325476;
    var H4 = 0xc3d2e1f0;
 
    // HASH COMPUTATION [�6.1.2]
 
    var W = new Array(80); var a, b, c, d, e;
    for (var i=0; i<N; i++) {
 
        // 1 - prepare message schedule 'W'
        for (var t=0;  t<16; t++) W[t] = M[i][t];
        for (var t=16; t<80; t++) W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
 
        // 2 - initialise five working variables a, b, c, d, e with previous hash value
        a = H0; b = H1; c = H2; d = H3; e = H4;
 
        // 3 - main loop
        for (var t=0; t<80; t++) {
            var s = Math.floor(t/20); // seq for blocks of 'f' functions and 'K' constants
            var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff;
            e = d;
            d = c;
            c = ROTL(b, 30);
            b = a;
            a = T;
        }
 
        // 4 - compute the new intermediate hash value
        H0 = (H0+a) & 0xffffffff;  // note 'addition modulo 2^32'
        H1 = (H1+b) & 0xffffffff; 
        H2 = (H2+c) & 0xffffffff; 
        H3 = (H3+d) & 0xffffffff; 
        H4 = (H4+e) & 0xffffffff;
    }
 
    return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr();
}
//
// extend Number class with a tailored hex-string method 
//   (note toString(16) is implementation-dependant, and 
//   in IE returns signed numbers when used on full words)
//
Number.prototype.toHexStr = function()
{
    var s="", v;
    for (var i=7; i>=0; i--) { v = (this>>>(i*4)) & 0xf; s += v.toString(16); }
    return s;
}